/************************************************************************
 * File: boardslot.cpp                                                  *
 *                                                                      *
 * Copyright 2006, 2008 Colin Kern (colin.kern@gmail.com)               *
 *                                                                      *
 * This file is part of Profit.  Some previous versions were released   *
 * under the names Megacorp Mania and Acquire.                          *
 *                                                                      *
 * Profit is free software: you can redistribute it and/or modify       *
 * it under the terms of the GNU General Public License as published by *
 * the Free Software Foundation, either version 3 of the License, or    *
 * any later version.                                                   *
 *                                                                      *
 * Profit is distributed in the hope that it will be useful,            *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 * GNU General Public License for more details.                         *
 *                                                                      *
 * You should have received a copy of the GNU General Public License    *
 * along with Profit.  If not, see <http://www.gnu.org/licenses/>.      *
 ************************************************************************/
#include "boardslot.h"
#include "company.h"
#include "tile.h"
#include <QPainter>
#include <QMouseEvent>

/*!
	\class BoardSlot
	\brief The BoardSlot class represents a single location on the board.
	
	A BoardSlot is a location on the board where a tile can be placed.  Once
	a tile is placed, that BoardSlot can then become part of a company if it
	is adjacent to a slot that is also part of a company.
	
	\sa Board, Company
*/
/*!
	\var m_isPlaced
	Stores whether a tile has been placed on this slot.
*/
/*!
	\var m_owner
	A pointer to the company that owns this slot, or 0 if no company owns it
	yet.
*/
/*!
	\var m_isFlagged
	This variable is used by various algorithms and has no semantic meaning in
	terms of the game.
*/


/*!
	Constructs a BoardSlot with the given parent.
	\param parent The parent of this BoardSlot. Default is 0.
*/
BoardSlot::BoardSlot(int row, int column, QWidget *parent)
	: QWidget(parent)
{
	m_isPlaced = false;
	m_owner = 0;
    unflag();
	setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
	m_row = row;
	m_column = column;
	m_hover = false;
	setGradientStops();
	setGradientColors();
}

/*!
	Returns whether a tile is placed on this BoardSlot.
	\return True if a tile has been placed here, otherwise false.
	\sa place(), remove()
*/
bool BoardSlot::isPlaced() const
{
    return m_isPlaced;
}

/*!
	Returns a pointer to the owner of this BoardSlot.
	\return A const pointer to a company, or 0.
	\sa setOwner(), setNoOwner()
*/
const Company* BoardSlot::getOwner() const
{
    return m_owner;
}

/*!
	Returns whether this slot is flagged or not.
	\return True if flagged, otherwise false.
	\sa flag(), unflag()
*/
bool BoardSlot::isFlagged() const
{
    return m_isFlagged;
}

/*!
	Returns whether this slot is owned by a company.
	\return True if owned, otherwise false.
	\sa getOwner(), setOwner()
*/
bool BoardSlot::isOwned() const
{
	return getOwner() != 0;
}

QSize BoardSlot::sizeHint() const
{
	return QSize(Width, Height);
}

/*!
	Sets this slot as having a tile placed on it.
	\sa remove(), isPlaced()
*/
void BoardSlot::place(bool invisible)
{
	if (!isPlaced()) {
		m_isPlaced = true;
		if (!invisible) {
			setGradientColors();
			setGradientStops();
			update();
		}
	}
}

/*!
	Sets this slot as not having a tile placed on it.  Also sets the owner
	of this slot to 0.
	\sa place(), isPlaced()
*/
void BoardSlot::remove(bool invisible)
{
	if (isPlaced()) {
		m_isPlaced = false;
		setOwner(0);
		if (!invisible) {
			setGradientColors();
			setGradientStops();
			update();
		}
	}
}

/*!
	Sets the owner of this slot.
	\param company The company that owns this slot.
	\sa getOwner()
*/
void BoardSlot::setOwner(Company &company)
{
	if (getOwner() != &company) {
		m_owner = &company;
		setGradientColors();
		update();
	}
}

/*!
	Sets the owner of this slot.
	\param company A pointer to the company that owns this slot.
	\sa getOwner()
*/
void BoardSlot::setOwner(Company *company)
{
	if (getOwner() != company) {
		m_owner = company;
		setGradientColors();
		update();
	}
}

/*!
	Flags this slot.
	\sa unflag(), isFlagged()
*/
void BoardSlot::flag()
{
    m_isFlagged = true;
}

/*!
 	Removes the flag on this slot.
 	\sa flag(), isFlagged()
*/
void BoardSlot::unflag()
{
    m_isFlagged = false;
}

/*!
	Returns a pointer to the owner of this BoardSlot.
	\return A pointer to a company, or 0.
	\sa setOwner(), setNoOwner()
*/
Company* BoardSlot::getOwner()
{
    return m_owner;
}

void BoardSlot::setHighlight(Highlight highlight)
{
	if (m_highlight != highlight) {
		m_highlight = highlight;
		setGradientColors();
		update();
	}
}

void BoardSlot::setValid(bool valid)
{
	if (m_valid != valid) {
		m_valid = valid;
		setGradientColors();
		update();
	}
}

void BoardSlot::setGradientStops()
{
	if (!isPlaced()) {
		qreal padx = rect().width() * .05;
		qreal pady = rect().height() * .05;
		m_bottomGradient.setStart(rect().topLeft() + QPointF(padx, pady));
		m_bottomGradient.setFinalStop(rect().bottomRight() - QPointF(padx * 2, pady * 2));
		
		padx = rect().width() * .07;
		pady = rect().height() * .07;
		QRectF topRect = QRectF(rect().topLeft() + QPointF(padx, pady), 
			rect().bottomRight() - QPointF(padx * 2, pady * 2));
		m_topGradient.setStart(topRect.topLeft());
		m_topGradient.setFinalStop(topRect.bottomRight());
	} else {
		m_bottomGradient.setStart(rect().topLeft());
		m_bottomGradient.setFinalStop(rect().bottomRight());
		
		qreal padx = rect().width() * .05;
		qreal pady = rect().height() * .05;
		QRectF topRect = QRectF(rect().topLeft() + QPointF(padx, pady), 
			rect().bottomRight() - QPointF(padx * 2, pady * 2));
		m_topGradient.setStart(topRect.topLeft());
		m_topGradient.setFinalStop(topRect.bottomRight());
	}
}

void BoardSlot::setGradientColors()
{
	if (!isPlaced()) {
		m_topGradient.setColorAt(0.0, QColor(64, 64, 64));
		m_topGradient.setColorAt(1.0, Qt::darkGray);	
		if (m_highlight == InHand) {
			if (!m_valid) {
				m_bottomGradient.setColorAt(0.0, QColor(196, 96, 96));
				m_bottomGradient.setColorAt(1.0, QColor(196, 96, 96));
			} else if (m_hover && m_phase == Profit::PlaceTile) {
				m_bottomGradient.setColorAt(0.0, QColor(96, 196, 255));
				m_bottomGradient.setColorAt(1.0, QColor(96, 196, 255));
			} else if (m_phase == Profit::PlaceTile) {
				m_bottomGradient.setColorAt(0.0, QColor(64, 128, 196));
				m_bottomGradient.setColorAt(1.0, QColor(64, 128, 196));
			} else {
				m_bottomGradient.setColorAt(0.0, QColor(64, 96, 128));
				m_bottomGradient.setColorAt(1.0, QColor(64, 96, 128));
			}
		} else {
			m_bottomGradient.setColorAt(0.0, Qt::darkGray);
			m_bottomGradient.setColorAt(1.0, QColor(64, 64, 64));
		}
	} else {	
		if (!isOwned()) {
			m_bottomGradient.setColorAt(0.0, Qt::gray);
			m_bottomGradient.setColorAt(1.0, Qt::darkGray);
			m_topGradient.setColorAt(0.0, Qt::darkGray);
			m_topGradient.setColorAt(1.0, Qt::lightGray);
		} else {
			QColor color = getOwner()->getColor();
			color.setHsv(color.hue(), color.saturation() - 128, color.value());
			m_bottomGradient.setColorAt(0.0, color);
			m_bottomGradient.setColorAt(1.0, color.darker(150));
			m_topGradient.setColorAt(0.0, color.darker(150));
			m_topGradient.setColorAt(1.0, color.lighter(115));
		}
	}
}

void BoardSlot::changePhase(Profit::Phase newPhase)
{
	m_phase = newPhase;
	if (m_highlight) {
		setGradientColors();
		update();
	}
	if (m_hover) {
		emit hoverChanged(m_hover, m_row, m_column);
	}
}

/*!
	Paints the contents of this item in local coordinates.  This is a virtual
	function of QGraphicsItem.
	\sa QGraphicsItem
*/
void BoardSlot::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);
	QRectF bottomRect;
	QRectF topRect;
	
	if (!isPlaced()) {
		qreal padx = rect().width() * .05;
		qreal pady = rect().height() * .05;
		int px1 = 1 > padx ? 1 : (int)padx;
		int py1 = 1 > pady ? 1 : (int)pady;
		int px2 = 1 > (padx * 2) ? 1 : (int)(padx * 2);
		int py2 = 1 > (pady * 2) ? 1 : (int)(pady * 2);
		bottomRect = QRect(rect().topLeft() + QPoint(px1, py1),
			rect().bottomRight() - QPoint(px2, py2));
		
		padx = rect().width() * .07;
		pady = rect().height() * .07;
		px1 = 1 > padx ? 1 : (int)padx;
		py1 = 1 > pady ? 1 : (int)pady;
		px2 = 1 > (padx * 2) ? 1 : (int)(padx * 2);
		py2 = 1 > (pady * 2) ? 1 : (int)(pady * 2);
		topRect = QRect(rect().topLeft() + QPoint(px1, py1), 
			rect().bottomRight() - QPoint(px2, py2));
	} else {
		bottomRect = rect();
		
		qreal padx = rect().width() * .05;
		qreal pady = rect().height() * .05;
		int px1 = 1 > padx ? 1 : (int)padx;
		int py1 = 1 > pady ? 1 : (int)pady;
		int px2 = 1 > (padx * 2) ? 1 : (int)(padx * 2);
		int py2 = 1 > (pady * 2) ? 1 : (int)(pady * 2);
		topRect = QRect(rect().topLeft() + QPoint(px1, py1), 
			rect().bottomRight() - QPoint(px2, py2));
	}
	
	painter.setBrush(QBrush(m_bottomGradient));
	painter.setPen(Qt::NoPen);
	painter.drawRect(bottomRect);
	
	painter.setBrush(QBrush(m_topGradient));
	painter.drawRect(topRect);
	
	/*
	painter.setPen(Qt::white);
	painter.setFont(QFont("Helvetica", 12, QFont::Bold));
	painter.drawText(topRect, Qt::AlignVCenter | Qt::AlignHCenter,
		Tile::toString(m_row, m_column));
	*/
}

void BoardSlot::mousePressEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton) {
		emit clicked(m_row, m_column);
	}
}

void BoardSlot::enterEvent(QEvent *event)
{
	m_hover = true;
	setGradientColors();
	update();
	emit hoverChanged(m_hover, m_row, m_column);
}

void BoardSlot::leaveEvent(QEvent *event)
{
	m_hover = false;
	setGradientColors();
	update();
	emit hoverChanged(m_hover, m_row, m_column);
}

void BoardSlot::resizeEvent(QResizeEvent *event)
{
	setGradientStops();
}